<script setup lang="ts">
import {Editor as MonacoTreeEditor, useMonaco, type Files} from '@/components/JEditor'
import {type ComputedRef, onMounted, ref} from 'vue'
import * as monaco from 'monaco-editor'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import {shikiToMonaco} from "@shikijs/monaco";
import {createHighlighter} from "shiki";
import type {LeftSiderBarItem} from "@/components/JEditor/domains/define";
import ItemTemp from "@/components/JEditor/left-sider-bar/ItemTemp.vue";
import IconsFile from "@/components/JEditor/icons/File.vue";
import IconsSetting from "@/components/JEditor/icons/Setting.vue";
import {
  DeleteFile,
  EditFile,
  GetConfigFiles,
  GetTemplateFiles,
  GetVarFiles,
  NewFile,
  RenameFile
} from "/wailsjs/go/api/EditorApi";

const props = defineProps({
  keyx: {
    type: String,
  },
  dir: {
    type: String,
  }
})


const currentActive = ref("Template");

async function handleClick(item: LeftSiderBarItem) {
  currentActive.value = item;
  await getFiles()
}

// ================ 初始化 init monaco-tree-editor ================


window.MonacoEnvironment = {
  getWorker: function (_moduleId, label: string) {
    if (label === 'json') {
      return new jsonWorker()
    } else if (label === 'ts' || label === 'typescript') {
      return new tsWorker()
    } else if (label === 'html' || label === 'handlebars' || label === 'razor') {
      return new htmlWorker()
    } else if (label === 'css' || label === 'scss' || label === 'less') {
      return new cssWorker()
    }
    return new editorWorker()
  },
  globalAPI: true,
}

onBeforeMount(async () => {
  const highlighter = await createHighlighter({
    // 这里的 themes 参数可以传入多个主题，
    // 在 https://shiki.tmrs.site/themes#%E4%B8%BB%E9%A2%98 查看更多
    themes: ["vitesse-dark", "vitesse-light", "andromeeda", "aurora-x", "github-dark", "github-light-default"],
    langs: ["javascript", "typescript", "vue", "java", "xml"],
  });
// // 首先注册你需要的语言的 IDs
  monaco.languages.register({id: 'vue'})
  monaco.languages.register({id: 'typescript'})
  monaco.languages.register({id: 'javascript'})
  monaco.languages.register({id: 'xml'})
  monaco.languages.register({id: 'java'})
  // 注册 Shiki 主题，并为 Monaco 提供语法高亮
  shikiToMonaco(highlighter, monaco);
})
const monacoStore = useMonaco(monaco)
onMounted(async () => {
  // 创建一个可复用的语法高亮器
  monacoStore.actions.setTheme('github-light-default')
  // await nextTick(() => {
  //   window.addEventListener('resize', () => {
  //     refreshKey.value += 1;
  //   });
  // })
  // registerRestl(monacoStore.actions.getMonaco())
})


// ================ 加载文件 load files ================
const files = ref<Files>()

async function getTemplateFiles() {
  return await GetTemplateFiles(props.dir, props.keyx)
}

async function getConfigFiles() {
  return await GetConfigFiles(props.keyx)
}

async function getVarFiles() {
  return await GetVarFiles(props.keyx)
}

async function getFiles() {
  let res
  if (currentActive.value === "Template") {
    res = await getTemplateFiles()
  } else if (currentActive.value === "Config") {
    res = await getConfigFiles()
  } else if (currentActive.value === "Var") {
    res = await getVarFiles()
  }
  files.value = res.data
}

const handleReload = async (resolve: () => void, reject: (msg?: string) => void) => {
  await getFiles()
  resolve();
}

const handleSaveFile = (path: string, content: string, resolve: () => void, reject: (msg?: string) => void) => {
  EditFile(path, content).then(() => {
    resolve()
  }).catch((e: Error) => {
    reject(e.message)
  })
}
const handleDeleteFile = (path: string, resolve: () => void, reject: (msg?: string) => void) => {
  DeleteFile(path).then(() => {
    resolve()
  }).catch((e: Error) => {
    reject(e.message)
  })
}
const handleDeleteFolder = (path: string, resolve: () => void, reject: (msg?: string) => void) => {
  DeleteFile(path).then(() => {
    resolve()
  }).catch((e: Error) => {
    reject(e.message)
  })
}
const handleNewFile = (path: string, resolve: Function, reject: Function) => {
  NewFile(path, false).then((_response) => {
    resolve()
  })
      .catch((e: Error) => {
        reject(e.message)
      })
}
const handleNewFolder = (path: string, resolve: Function, reject: Function) => {
  NewFile(path, true).then((_response) => {
    resolve()
  })
      .catch((e: Error) => {
        reject(e.message)
      })
}
const handleRename = (path: string, newPath: string, resolve: () => void, reject: (msg?: string) => void) => {
  RenameFile(path, newPath).then(() => {
    resolve()
  }).catch((e: Error) => {
    reject(e)
  })
}


const handleContextMenuSelect = (path: string, item: { label: string | ComputedRef<string>; value: string }) => {
  console.warn('path: ' + path + '\nitem: ' + item)
}

// ================ 拖拽事件 drag event =================
/**
 * 当把拖动文件树中的数据拖进编辑器时，在当前光标处插入自定义的import语句
 * When drag filelist data into monaco editor, insert custom statement at cursor position
 */
// const handleDragInEditor = (srcPath: string, targetPath: string, type: 'file' | 'folder') => {
//   if (!targetPath.endsWith('.ts') && !srcPath.endsWith('.js')) {
//     return
//   }
//   const editor = monacoStore.actions.getEditor()
//   const lineIndex = editor.getPosition()?.lineNumber!
//   let str = 'import "' + _relativePathFrom(srcPath, targetPath) + '"'
//   editor.executeEdits('drop', [{range: new monaco.Range(lineIndex, 0, lineIndex, 0), text: str}])
// }
//
// function _longestCommonPrefix(strs: string[]): string {
//   if (!strs.length) return ''
//   let [a, ...b] = strs
//   let result = ''
//   for (let i = 0; i < a.length; i++) {
//     let flag = b.every((item) => item[i] === a[i])
//     if (flag) result += a[i]
//     else break
//   }
//   return result
// }
//
// //计算相对路径 getRelativePath
// const _relativePathFrom = (returnPath: string, fromPath: string): string => {
//   const prefix = _longestCommonPrefix([returnPath, fromPath])
//   returnPath = returnPath.replace(prefix, '').replace(/\\/g, '/')
//   fromPath = fromPath.replace(prefix, '').replace(/\\/g, '/')
//   const fromPathArr = fromPath.split('/')
//   let relativePath = ''
//   if (fromPathArr.length === 1) {
//     relativePath = './'
//   } else {
//     for (let i = fromPathArr.length - 2; i >= 0; i--) {
//       relativePath += '../'
//     }
//   }
//   return (relativePath += returnPath)
// }
</script>

<template>


  <MonacoTreeEditor
      :font-size="16"
      :files="files"
      :sider-min-width="240"
      language="zh-CN"
      theme="dark"
      filelistTitle="文件"
      @reload="handleReload"
      @new-file="handleNewFile"
      @new-folder="handleNewFolder"
      @save-file="handleSaveFile"
      @delete-file="handleDeleteFile"
      @delete-folder="handleDeleteFolder"
      @rename-file="handleRename"
      @rename-folder="handleRename"
      @contextmenu-select="handleContextMenuSelect"
      ref="editorRef"
  >
    <template #left>
      <ItemTemp
          @click="handleClick('Template')"
          :current-active="currentActive"
          name="Template"
          title="模板文件"
      >
        <IconsFile/>
      </ItemTemp>

      <ItemTemp
          @click="handleClick('Config')"
          :current-active="currentActive"
          name="Config"
          title="配置文件"
      >
        <IconsSetting/>
      </ItemTemp>

      <ItemTemp
          @click="handleClick('Var')"
          :current-active="currentActive"
          name="Var"
          title="模板变量"
      >
        <q-icon name="display_settings" size="md"></q-icon>
      </ItemTemp>
    </template>

  </MonacoTreeEditor>

</template>
